package;

import nme.display.MovieClip;
import nme.display.Bitmap;
import nme.display.Shape;
import nme.geom.Point;
import com.eclecticdesignstudio.spritesheet.importers.SpriteLoq;
import com.eclecticdesignstudio.spritesheet.AnimatedSprite;

/**
 * @author jonathanmoriarty
 */
class HumanPlayer extends MovieClip, implements Player
{
	public var hitBox:Shape;
	
	// character specific data
	public var _sprite:AnimatedSprite;
	//public var _sprite:Bitmap;
	private var _moveList:Array<Dynamic>;
	private var _height:Float;
	private var _width:Float;
	private var _moveSpeed:Float;
	private var _jumpSpeed:Float;
	
	private var _direction:Int;
	
	private var _xVelocity:Float;
	private var _yVelocity:Float;
	
	private var _inAir:Bool;
	private var _onGround:Bool;
	private var _doingMove:Bool;
	
	private var _health:Int;
	
	private static var SPRITE_X_OFFSET:Float = -70;
	private static var SPRITE_Y_OFFSET:Float = -220;
	
	private static var WALK_SPEED:Float = 3;
	private static var RUN_SPEED:Float = 6;
	private static var JUMP_SPEED:Float = 13;
	
	public function new( l_characterName:String, l_x:Float, l_y:Float, l_direction:Int ) 
	{	
		super();
		
		setX( l_x );
		setY( l_y );
		
		// TODO: should fetch move list, speed, jump height, sprite
		loadCharacter( l_characterName );
		setHitBox();
		
		_xVelocity = 0;
		_yVelocity = 0;
		
		setDirection( l_direction );
		setOnGround( true );
		
		_doingMove = false;	
	}
	
	public function loadCharacter( l_characterName:String ):Void
	{
		/*var l_characterData:haxe.xml.Fast = Tools.loadXML( l_characterName );
		_moveList = new Array<Dynamic>();*/
		//trace(l_characterName);
		
		l_characterName += "_anims";
		//trace(l_characterName);
		
		var l_spriteSheet = Tools.loadSpriteSheet( l_characterName );
		_sprite = new AnimatedSprite( l_spriteSheet );
		_sprite.showBehavior( "idle" );
		_sprite.x += SPRITE_X_OFFSET/2;
		_sprite.y += SPRITE_Y_OFFSET;
		addChild( _sprite );
		//trace("executes");
		
		/* Here's how to load a sprite sheet Jon, things to note for NME:
			-every update you need to call sprite.update(l_deltaTime) on every frame to keep it playing.
			-you can get what animation is is playing with sprite.currentBehavior.name property as a string.
			-you can't get the width or height of a sprite
			-_sprite.showBehavior( "kliibu_idle" ); calls the "kliibu_idle, you can find all the animation names in the kliibu_anims.xml files in assets"
			
		_sprite = Tools.loadBitmap( l_characterName + "Placeholder" );
		_sprite.x = -_sprite.width/2;
		_sprite.y = -_sprite.height;
		addChild( _sprite );*/
		
		//TODO: load from xml
		_health = 100;
	}
	
	public function getHealth():Int
	{
		return _health;
	}
	
	public function updateHealth( l_healthChange:Int ):Void
	{
		_health += l_healthChange;
	}
	
	public function inAir():Bool
	{
		return _inAir;
	}
	
	public function setInAir( l_newInAir:Bool ):Void
	{
		_inAir = l_newInAir;
		if ( _inAir )
		{
			setOnGround( false );
		}
	}
	
	public function onGround():Bool
	{
		return _onGround;
	}
	
	public function setOnGround( l_newOnGround:Bool ):Void
	{
		_onGround = l_newOnGround;
		if ( _onGround )
		{
			setInAir( false );
		}
	}
	
	public function getX():Float
	{
		return x;
	}
	
	public function setX( l_newX:Float ):Void
	{
		x = l_newX;
	}
	
	public function getXVelocity():Float
	{
		return _xVelocity;
	}
	
	public function setXVelocity( l_newXVelocity:Float ):Void
	{
		_xVelocity = l_newXVelocity;
	}
	
	public function getY():Float
	{
		return y;
	}
	
	public function setY( l_newY:Float ):Void
	{
		y = l_newY;
	}
	
	public function getYVelocity():Float
	{
		return _yVelocity;
	}
	
	public function setYVelocity( l_newYVelocity:Float ):Void
	{
		_yVelocity = l_newYVelocity;
	}
	
	/*public function setSprite( l_spriteString:String ):Void
	{
		var l_spriteSheet = Tools.loadSpriteSheet( l_spriteString );
		_sprite = new AnimatedSprite( l_spriteSheet );
		_sprite.showBehavior( "idle" );
		_sprite.x = 0;
		_sprite.y = 0;
		addChild( _sprite );
	}*/
	
	public function setHitBox():Void
	{
		hitBox = new Shape();
		hitBox.visible = false;
		//hitBox.alpha = .5;
		hitBox.graphics.lineStyle();
		hitBox.graphics.beginFill( 0x00FF00, 1 );
		//TODO: Pull size from character list, 
		// maybe second sprite sheet of hitbox according to character for max prescision -JM
		//hitBox.graphics.drawRect( 0, 0, -SPRITE_X_OFFSET, -SPRITE_X_OFFSET );
		hitBox.graphics.drawRect( 0, 0, -SPRITE_X_OFFSET, -SPRITE_Y_OFFSET );
		hitBox.graphics.endFill();
		hitBox.x = -hitBox.width/2;
		hitBox.y = -hitBox.height;
		addChild( hitBox );
	}
	
	public function getDirection():Int
	{
		return _direction;
	}
	
	public function setDirection( l_newDirection:Int ):Void
	{
		if ( l_newDirection == 1 || l_newDirection == -1 )
		{
			_direction = l_newDirection;
			this.scaleX = _direction;
		}
	}
	
	public function findMove( l_inputQueue:Array<Dynamic> ):String 
	{
		return null;
	}
	
	public function update( l_deltaTime:Int, l_inputQueue:Array<Dynamic> ):Void 
	{	
		// Put the code for movement stuff in here,
		// based on button variable in PlayScreen.
		// Crude example shown below. -JM
		
		
		var l_dead:Bool = false;
		if ( _health <= 0 )
		{
			playAnimation( "defeat" );
			_xVelocity = 0;
			_yVelocity = 0;
			l_dead = true;
		}
		
		var l_stateChange:Bool = false;
		if ( !l_dead && !l_stateChange && !_doingMove )
		{
			var foundMove:String = findMove( l_inputQueue );
			if ( foundMove != null )
			{
				// have the sprite play the named move
				l_stateChange = true;
				_doingMove = true;
			}
			else if ( !l_stateChange && onGround() )
			{
				if ( InputManager.isKeyDown( InputManager.LEFT_KEY ) )
				{
					if (getDirection() == 1)
					{
						setDirection(-1);
					}
					
					if ( _sprite.currentBehavior.name.indexOf("run") != -1 || ( l_inputQueue.length != 0 && l_inputQueue[l_inputQueue.length - 1] == InputManager.LEFT_KEY ) )
					{
						_xVelocity += -RUN_SPEED;
					}
					else
					{
						_xVelocity += -WALK_SPEED;
					}
				}
				
				if ( InputManager.isKeyDown( InputManager.RIGHT_KEY ) )
				{
					if (getDirection() == -1)
					{
						setDirection(1);
					}
					if ( _sprite.currentBehavior.name.indexOf("run") != -1 || ( l_inputQueue.length != 0 && l_inputQueue[l_inputQueue.length - 1] == InputManager.RIGHT_KEY ) )
					{
						_xVelocity += RUN_SPEED;
					}
					else
					{
						/*if ( l_inputQueue.length != 0 )
						{
							trace( l_inputQueue[ l_inputQueue.length - 1 ] );
						}
						else
						{
							trace("queue empty");
						}*/
						_xVelocity += WALK_SPEED;
					}
				}
				
				if ( InputManager.isKeyDown( InputManager.DOWN_KEY ) )
				{
					if ( _xVelocity == 0 )
					{
						playAnimation( "kneel_idle");
					}
				}
				
				if ( InputManager.isKeyPressed( InputManager.SPACE_KEY ) )
				{
					l_stateChange = true;
					_yVelocity += -JUMP_SPEED;
					setInAir( true );
					playAnimation( "jump");
				}
				
				if ( _xVelocity == 0 && _yVelocity == 0 && InputManager.isKeyDown( InputManager.B_KEY ) )
				{
					//trace("block");
					playAnimation( "block");
				}
				
				if ( InputManager.isKeyPressed( InputManager.F_KEY ) )
				{
					//trace("punch");
					_doingMove = true;
					
					if ( InputManager.isKeyDown( InputManager.UP_KEY ) || InputManager.isKeyPressed( InputManager.UP_KEY ) )
					{
						playAnimation( "high_punch" );
					}
					else if ( InputManager.isKeyDown( InputManager.DOWN_KEY ) || InputManager.isKeyPressed( InputManager.DOWN_KEY ) )
					{
						playAnimation( "low_punch" );
					}
					else
					{
						playAnimation( "mid_punch" );
					}
				}
				else if ( InputManager.isKeyPressed( InputManager.R_KEY ) )
				{
					//trace("punch");
					_doingMove = true;
					
					if ( InputManager.isKeyDown( InputManager.UP_KEY ) || InputManager.isKeyPressed( InputManager.UP_KEY ) )
					{
						playAnimation( "high_kick" );
					}
					else if ( InputManager.isKeyDown( InputManager.DOWN_KEY ) || InputManager.isKeyPressed( InputManager.DOWN_KEY ) )
					{
						playAnimation( "low_kick" );
					}
					else
					{
						playAnimation( "mid_kick" );
					}
				} 
			}
			else if ( !l_stateChange && inAir() )
			{
				_yVelocity += .6;
				if ( y + _yVelocity >= PlayScreen.getGroundLevel( x ) )
				{
					l_stateChange = true;
					_yVelocity = PlayScreen.getGroundLevel( x ) - y;
					setOnGround( true );
					//trace("this plays");
					playAnimation( "land" );
				}
			}
			
			// do boundary level check / adjust here
		}
		else if ( !l_dead && !l_stateChange && _doingMove )
		{
			
		}
		
		updateAnimations(l_deltaTime);
		
		x += _xVelocity;
		y += _yVelocity;
		
		if ( onGround() )
		{
			_yVelocity = 0;
			_xVelocity = 0;
		}
	}
	
	public function updateAnimations( l_deltaTime:Int ):Void 
	{
		if ( onGround() )
		{
			if ( !_doingMove )
			{
				if ( _sprite.currentBehavior.name.indexOf("land") == -1 )
				{
					if ( Math.abs(_xVelocity) == WALK_SPEED )
					{
						playAnimation( "walk_move" );
						//trace("walk plays");
					}
					else if ( Math.abs(_xVelocity) == RUN_SPEED )
					{
						playAnimation( "run_move" );
						//trace("run plays");
					}
					else if ( InputManager.isKeyDown( InputManager.DOWN_KEY ) )
					{
						playAnimation( "kneel_idle" );
					}
					else if ( !InputManager.isKeyDown( InputManager.B_KEY ) )
					{
						//trace("gets here");
						playAnimation( "idle" );
					}
				}
			}
			else
			{
			
			}
		}
		else if ( inAir() )
		{
		
		}
		
		_sprite.update(l_deltaTime);
		if ( _sprite.currentBehavior.name.indexOf("punch") == -1 && _sprite.currentBehavior.name.indexOf("kick") == -1 )
		{
			_doingMove = false;
		}
	}
	
	public function playAnimation( l_name:String ):Void 
	{
		//trace(l_name);
		if ( _sprite.currentBehavior.name.indexOf("defeat") == -1 )
		{
			if ( ( l_name.indexOf("punch") != -1 && _sprite.currentBehavior.name.indexOf("punch") == -1 )
			  || ( l_name.indexOf("kick") != -1 && _sprite.currentBehavior.name.indexOf("kick") == -1 ) )
			{
				//trace("start move: " + l_name);
				var l_prev:String = _sprite.currentBehavior.name;
				_sprite.showBehaviors( [ l_name, l_prev ] );
				//trace("punch");
			}
			else if ( l_name.indexOf("move") != -1 && _sprite.currentBehavior.name.indexOf("move") == -1 && _sprite.currentBehavior.name.indexOf("end") == -1 )
			{
				//trace("start move: " + l_name);
				_sprite.showBehaviors( [ "start_move", l_name ] );
				//trace("move");
			}
			else if ( l_name.indexOf("kneel") != -1 && _sprite.currentBehavior.name.indexOf("kneel") == -1 )
			{
				_sprite.showBehaviors( [ "start_kneel", l_name ] );
				//trace("start kneel");
			}
			else if ( l_name.indexOf("kneel") == -1 && _sprite.currentBehavior.name.indexOf("kneel") != -1 && _sprite.currentBehavior.name.indexOf("end") == -1 )
			{
				_sprite.showBehaviors( [ "end_kneel", l_name ] );
				//trace("end kneel");
			}
			else if ( l_name.indexOf("land") != -1 && _sprite.currentBehavior.name.indexOf("land") == -1 )
			{
				_sprite.showBehaviors( [ l_name, "idle" ] );
				//trace("land");
			}
			else if ( _sprite.currentBehavior.name != l_name && _sprite.currentBehavior.name.indexOf("start") == -1 && _sprite.currentBehavior.name.indexOf("end") == -1 && _sprite.currentBehavior.name.indexOf("land") == -1 )
			{
				_sprite.showBehavior( l_name );
				//trace("normal");
			}
		}
	}
}